from rest_framework import generics, status, permissions
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
from django.db.models import Count, Sum, Avg
from django.utils import timezone
from datetime import timedelta
from .models import (
    AdSpace, Advertisement, AdClick,
    AdImpression, AdCampaign, AdPricing
)
from .serializers import (
    AdSpaceSerializer, AdSpaceListSerializer,
    AdvertisementSerializer, AdvertisementCreateSerializer,
    AdvertisementAdminSerializer, AdStatsSerializer,
    AdSpaceStatsSerializer, CampaignPerformanceSerializer,
    AdCampaignSerializer, AdCampaignCreateSerializer,
    AdPricingSerializer
)
from .filters import (
    AdSpaceFilter, AdvertisementFilter,
    AdCampaignFilter, AdPricingFilter
)


class AdSpaceListView(generics.ListAPIView):
    queryset = AdSpace.objects.filter(is_active=True)
    serializer_class = AdSpaceListSerializer
    permission_classes = [permissions.AllowAny]
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_class = AdSpaceFilter
    ordering_fields = ['name', 'base_price']
    ordering = ['name']


class AdSpaceAdminListView(generics.ListCreateAPIView):
    queryset = AdSpace.objects.all()
    serializer_class = AdSpaceSerializer
    permission_classes = [permissions.IsAdminUser]
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_class = AdSpaceFilter
    ordering_fields = ['name', 'base_price', 'created_at']
    ordering = ['-created_at']


class AdSpaceDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = AdSpace.objects.all()
    serializer_class = AdSpaceSerializer
    permission_classes = [permissions.IsAdminUser]


class AdvertisementListView(generics.ListAPIView):
    serializer_class = AdvertisementSerializer
    permission_classes = [permissions.AllowAny]
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_class = AdvertisementFilter
    ordering_fields = ['priority', 'start_date', 'created_at']
    ordering = ['-priority', '-created_at']
    
    def get_queryset(self):
        today = timezone.now().date()
        return Advertisement.objects.filter(
            status='active',
            start_date__lte=today,
            end_date__gte=today
        ).select_related('ad_space')


class AdvertisementAdminListView(generics.ListCreateAPIView):
    queryset = Advertisement.objects.all()
    serializer_class = AdvertisementAdminSerializer
    permission_classes = [permissions.IsAdminUser]
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_class = AdvertisementFilter
    ordering_fields = ['created_at', 'start_date', 'status']
    ordering = ['-created_at']


class AdvertisementAdminDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Advertisement.objects.all()
    serializer_class = AdvertisementAdminSerializer
    permission_classes = [permissions.IsAdminUser]


class AdvertisementCreateView(generics.CreateAPIView):
    serializer_class = AdvertisementCreateSerializer
    permission_classes = [permissions.IsAuthenticated]
    
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        advertisement = serializer.save(advertiser=request.user)
        
        return Response(
            AdvertisementSerializer(advertisement).data,
            status=status.HTTP_201_CREATED
        )


@api_view(['POST'])
@permission_classes([permissions.AllowAny])
def track_impression(request, ad_id):
    try:
        advertisement = Advertisement.objects.get(id=ad_id)
    except Advertisement.DoesNotExist:
        return Response(
            {'error': '广告不存在'},
            status=status.HTTP_404_NOT_FOUND
        )
    
    # 记录展示
    AdImpression.objects.create(
        advertisement=advertisement,
        user=request.user if request.user.is_authenticated else None,
        ip_address=get_client_ip(request),
        user_agent=request.META.get('HTTP_USER_AGENT', '')
    )
    
    # 更新广告展示计数
    advertisement.view_count += 1
    advertisement.save()
    
    return Response({'message': '展示已记录'})


@api_view(['POST'])
@permission_classes([permissions.AllowAny])
def track_click(request, ad_id):
    try:
        advertisement = Advertisement.objects.get(id=ad_id)
    except Advertisement.DoesNotExist:
        return Response(
            {'error': '广告不存在'},
            status=status.HTTP_404_NOT_FOUND
        )
    
    # 记录点击
    AdClick.objects.create(
        advertisement=advertisement,
        user=request.user if request.user.is_authenticated else None,
        ip_address=get_client_ip(request),
        user_agent=request.META.get('HTTP_USER_AGENT', '')
    )
    
    # 更新广告点击计数
    advertisement.click_count += 1
    advertisement.save()
    
    return Response({'message': '点击已记录'})


@api_view(['GET'])
@permission_classes([permissions.IsAdminUser])
def ad_performance_report(request):
    days = int(request.GET.get('days', 30))
    end_date = timezone.now().date()
    start_date = end_date - timedelta(days=days)
    
    # 广告空间统计
    ad_space_stats = AdSpace.objects.annotate(
        total_impressions=Count('advertisements__impressions'),
        total_clicks=Count('advertisements__clicks'),
        revenue=Sum('advertisements__total_budget')
    ).filter(
        total_impressions__gt=0
    ).values(
        'name', 'total_impressions', 'total_clicks', 'revenue'
    )
    
    # 广告统计
    ad_stats = Advertisement.objects.filter(
        created_at__date__gte=start_date
    ).aggregate(
        total_impressions=Sum('view_count'),
        total_clicks=Sum('click_count'),
        total_spent=Sum('spent_amount')
    )
    
    # 计算CTR和CPC
    total_impressions = ad_stats['total_impressions'] or 0
    total_clicks = ad_stats['total_clicks'] or 0
    total_spent = ad_stats['total_spent'] or 0
    
    click_through_rate = (total_clicks / total_impressions * 100) if total_impressions > 0 else 0
    cost_per_click = (total_spent / total_clicks) if total_clicks > 0 else 0
    
    stats = AdStatsSerializer({
        'total_impressions': total_impressions,
        'total_clicks': total_clicks,
        'click_through_rate': click_through_rate,
        'total_spent': total_spent,
        'cost_per_click': cost_per_click
    }).data
    
    return Response({
        'ad_space_stats': list(ad_space_stats),
        'overall_stats': stats
    })


@api_view(['GET'])
@permission_classes([permissions.IsAdminUser])
def campaign_performance(request):
    days = int(request.GET.get('days', 30))
    end_date = timezone.now().date()
    start_date = end_date - timedelta(days=days)
    
    campaigns = AdCampaign.objects.filter(
        created_at__date__gte=start_date
    ).annotate(
        impressions=Sum('advertisements__view_count'),
        clicks=Sum('advertisements__click_count'),
        spent=Sum('advertisements__spent_amount')
    ).values(
        'name', 'impressions', 'clicks', 'spent'
    )
    
    # 计算CTR和CPC
    campaign_data = []
    for campaign in campaigns:
        impressions = campaign['impressions'] or 0
        clicks = campaign['clicks'] or 0
        spent = campaign['spent'] or 0
        
        ctr = (clicks / impressions * 100) if impressions > 0 else 0
        cpc = (spent / clicks) if clicks > 0 else 0
        
        campaign_data.append({
            'campaign_name': campaign['name'],
            'impressions': impressions,
            'clicks': clicks,
            'ctr': ctr,
            'spent': spent,
            'cpc': cpc
        })
    
    serializer = CampaignPerformanceSerializer(campaign_data, many=True)
    return Response(serializer.data)


@api_view(['GET'])
@permission_classes([permissions.IsAdminUser])
def ad_daily_report(request):
    days = int(request.GET.get('days', 7))
    end_date = timezone.now().date()
    start_date = end_date - timedelta(days=days)
    
    daily_data = []
    for i in range(days):
        date = start_date + timedelta(days=i)
        
        impressions = AdImpression.objects.filter(
            created_at__date=date
        ).count()
        
        clicks = AdClick.objects.filter(
            created_at__date=date
        ).count()
        
        ctr = (clicks / impressions * 100) if impressions > 0 else 0
        
        daily_data.append({
            'date': date.isoformat(),
            'impressions': impressions,
            'clicks': clicks,
            'ctr': ctr,
            'revenue': 0  # 简化处理
        })
    
    return Response(daily_data)


class AdCampaignListView(generics.ListCreateAPIView):
    queryset = AdCampaign.objects.all()
    serializer_class = AdCampaignSerializer
    permission_classes = [permissions.IsAuthenticated]
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_class = AdCampaignFilter
    ordering_fields = ['name', 'start_date', 'created_at']
    ordering = ['-created_at']


class AdCampaignDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = AdCampaign.objects.all()
    serializer_class = AdCampaignSerializer
    permission_classes = [permissions.IsAuthenticated]


class AdCampaignCreateView(generics.CreateAPIView):
    serializer_class = AdCampaignCreateSerializer
    permission_classes = [permissions.IsAuthenticated]
    
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        campaign = serializer.save(advertiser=request.user)
        
        return Response(
            AdCampaignSerializer(campaign).data,
            status=status.HTTP_201_CREATED
        )


class AdPricingListView(generics.ListCreateAPIView):
    queryset = AdPricing.objects.all()
    serializer_class = AdPricingSerializer
    permission_classes = [permissions.IsAdminUser]
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_class = AdPricingFilter
    ordering_fields = ['ad_space', 'base_price', 'valid_from']
    ordering = ['-valid_from']


class AdPricingDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = AdPricing.objects.all()
    serializer_class = AdPricingSerializer
    permission_classes = [permissions.IsAdminUser]


def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip
